define(["jquery", "String"], function ($, String) {
    function Validator() {
    }

    Validator.hasCustomValidator = false;

    Validator.isOnlyOne = true;

    Validator.option = {callback: {}, args: {}};


    Validator._check = function (options) {
        if (options == undefined || options == null) {
            return validator;
        }

        if (!(options instanceof Array || options instanceof Validator.option)) {
            throw 'Parameter[validators] is neither function nor array.';
        }

        if (options instanceof Validator.options) {
            if (options.callback == undefined || options.callback == null) {
                throw 'Parameter[validators] is neither function nor array.';
            }

            if (typeof options.callback !== 'function') {
                throw 'Parameter[validators] is neither function nor array.';
            }
            Validator.hasCustomValidator = true;
            return;
        }

        if (options instanceof Array) {
            $.each(options, function (index, option) {
                Validator.isOnlyOne = false;
                Validator._check(option);
            });
        }
    }

    Validator.prototype = {
        required_attr: 'data-val_required',
        customValidators: [],
        _getDisplayname: function () {
            return $("label[for=" + id + "]").text();
        },

        /*_getPasswordInfos: function () {
            var passwords = $("input[type=password]");
            var passwordInfo = [{"k": " 0", "v": "old"}, {"k": "1", "v": "new"}, {"k": "2", "v": "confirm"}];
            var result = {};
            var oldPassword = null;
            var newPassword = null;
            var confirmPassword = null;
            $.each(passwords, function (index, domEle) {
                var type = $(domEle).attr("data-password_type");
                var value = $(domEle).val();

                $.each(passwordInfo, function (i, ele) {
                    if (ele.k == type) {
                        var id = $(domEle).attr("id");
                        var item = {};
                        item["value"] = value;
                        item["name"] = id;
                        item["display_name"] = this._getDisplayname(id);
                        result[ele.v] = item;
                    }
                });
            })

            return result;
        },

        _checkPassword: function (formId) {
            var passwords = this._getPasswordInfos();
            var oldPassword = passwords["old"] == undefined ? undefined : passwords["old"].value;
            var newPassword = passwords["new"] == undefined ? undefined : passwords["new"].value;
            var confirmPassword = passwords["confirm"] == undefined ? undefined : passwords["confirm"].value;

            if (oldPassword == undefined
                && newPassword == undefined
                && confirmPassword == undefined) {
                return true;
            }

            var orderInstanceId = $("#node_instance_id").val();
            if (orderInstanceId.length > 0) {
                //编辑的情况
                if (!(oldPassword == undefined && newPassword == undefined)
                    || !(oldPassword != undefined && newPassword != undefined)) {
                    alert("The order should be have two fields [old password ,new password] to make a pair.");
                    return false;
                }
            }

            if (!(confirmPassword != undefined && newPassword != undefined)) {
                alert("The order should be have two fields [new password ,confirm password] to make a pair.");
                return false;
            }

            if (orderInstanceId.length > 0) {
                if (oldPassword == newPassword) {
                    alert("The value of old password field should not be equals to new password field.");
                    $("#" + passwords["new"].name).focus();
                    return false;
                }
                var strPassword = passwords["old"].value;
                if (!this._validatePassword(strPassword)) {
                    alert(String.format("密码域[%s]的数据格式必须采用数字、字母、特殊字符且长度为6-20位的字符串.", this._getDisplayname(passwords["old"].name)));
                    $("#" + passwords["old"].name).focus();
                    return false;
                }
            }

            if (newPassword != confirmPassword) {
                alert("The value of new password field should be equals to confirm password field.");
                $("#" + passwords["confirm"].name).focus();
                return false;
            }

            if (!this._validatePassword(passwords["new"].value)) {
                alert(String.format("密码域[%s]的数据格式必须采用数字、字母、特殊字符且长度为6-20位的字符串.", this._getDisplayname(passwords["new"].name)));
                $("#" + passwords["new"].name).focus();
                return false;
            }

            if (!this._validatePassword(passwords["confirm"].value)) {
                alert(String.format("密码域[%s]的数据格式必须采用数字、字母、特殊字符且长度为6-20位的字符串.", this._getDisplayname(passwords["confirm"].name)));
                $("#" + passwords["confirm"].name).focus();
                return false;
            }

            return true;
        },*/

        _validateDateComponents: function () {
            var result = {};
            result['status'] = true;
            var dates = $("input[data-type=date]");
            $.each(dates, function (index, domEle) {
                var required = $(domEle).attr(required_attr);
                var value = $(domEle).val();

                if (required == undefined) {
                    return;
                }

                if (value.length == 0) {
                    result['status'] = false;
                    result['name'] = $(domEle).attr('id');
                    result['tip'] = $(domEle).attr(required_attr);
                    return;
                }

                if ($(domEle).attr('data-date-format') == 'yyyy-MM-dd') {
                    if (this._isNotDate(value)) {
                        result['status'] = false;
                        result['name'] = $(domEle).attr('id');
                        result['tip'] = '不符合格式[yyyy-MM-dd]';
                        return;
                    }
                }
            });

            return result;
        },

        _validateSelectComponents: function () {
            var result = {};
            result['status'] = true;
            var selectObjs = $("select");
            $.each(selectObjs, function (index, domEle) {
                var required = $(domEle).attr(required_attr);
                var value = $(domEle).val();

                if (required == undefined) {
                    return;
                }

                if (typeof (value) instanceof Array) {
                    console.log('valuexxxx-->' + value)
                }
                console.log('value-->' + value)
                if (String.isEmpty(value)) {
                    result['status'] = false;
                    result['name'] = $(domEle).attr('id');
                    result['tip'] = $(domEle).attr(required_attr);
                    return;
                }
            });
            return result;
        },

        _checkRequireds: function () {
            var results = [];
            var i = 0
            var selectObjs = $("input");
            $.each(selectObjs, function (index, domEle) {
                var required = $(domEle).attr(required_attr);
                var value = $(domEle).val();
                if (required == undefined) {
                    return;
                }
                console.log(required);
                if (String.isEmpty(value)) {
                    var res = {};
                    res["status"] = false;
                    res['name'] = $(domEle).attr('id');
                    res['tip'] = required;
                    results[i] = res;
                    i++;
                    return;
                }
            });
            return results;
        },

        /**
         * 只驗證日期的情況
         * @param date
         * @returns {boolean}
         */
        _isNotDate: function (date) {
            var reg = /((^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(10|12|0?[13578])([-\/\._])(3[01]|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(11|0?[469])([-\/\._])(30|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(0?2)([-\/\._])(2[0-8]|1[0-9]|0?[1-9])$)|(^([2468][048]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([3579][26]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][13579][26])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][13579][26])([-\/\._])(0?2)([-\/\._])(29)$))/ig;
            if (!reg.test(date)) {
                return true;
            }
            return false;
        },

        /**
         * 验证日期时间格式为：2012-01-31 09:00:22
         */
        _validateDatetime: function (strDate) {
            var reDateTime = /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]:[0-5][0-9]$/;
            return reDateTime.test(strDate);
        },

        /**
         * 验证日期时间，只验证到分钟的情况：
         * 验证格式为：2012-01-31 09:01
         */
        _validateDatetime2: function (strDate) {
            var reDateTime = /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]$/;
            return reDateTime.test(strDate);
        },

        /**
         * 验证时间
         * @param strTime
         * @returns {boolean}
         */
        _validateTime: function (strTime) {
            var regTime = /^([0-2][0-3]):([0-5][0-9]):([0-5][0-9])$/;
            return regTime.test(strTime);
        },

        _validateDataFormat: function () {
            var items = [];
            var inputObjs = $("input[type=text]");

            $.each(inputObjs, function (index, el) {
                // var required = $(domEle).attr(required_attr);
                var dataType = $(el).attr("data-type");
                if (dataType == undefined) {
                    return;
                }

                if (dataType == "String") {
                    return;
                }

                if (dataType == "date") {
                    return;
                }

                if (dataType == "number") {
                    dataType = "Number";
                }

                var value = $(el).val();
                if (value.isEmpty()) {
                    return;
                }

                var id = $(el).attr('id');
                var displayname = this._getDisplayname(id);

                var funcName = String.format("validate%s", dataType);
                var args = [];
                args.push(value);

                var succ = this._execDynamicMethod_(funcName, args);
                if (!succ) {
                    var item = {};
                    item["name"] = id;
                    item["tip"] = displayname;
                    items.push(item);
                }
            });

            var result = {};
            result["status"] = true;
            if (items.length == 0) {
                return result;
            }

            result["status"] = false;
            result["items"] = items;
            return result;
        },

        _validateNumber: function (val) {
            //非负浮点数
            var regPos = /^\d+(\.\d+)?$/;
            //负浮点数
            var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/;
            if (regPos.test(val) || regNeg.test(val)) {
                return true;
            }
            return false;
        },

        _validateCreditcard: function () {
            number = number.replace(/\s\S/g, "");
            var length = number.length;
            var wei = [];
            for (var i = 0; i < length; i++) {
                // 从最末一位开始提取，每一位上的数值
                wei.push(parseInt(number.substring(length - i - 1, length - i)));
                console.log("第" + i + "位数字是：" + wei[i]);
            }
            var sumOdd = 0;
            var sumEven = 0;
            for (var i = 0; i < length / 2; i++) {
                sumOdd += wei[2 * i];
                if ((wei[2 * i + 1] * 2) > 9) {
                    wei[2 * i + 1] = wei[2 * i + 1] * 2 - 9;
                }
                else {
                    wei[2 * i + 1] *= 2;
                }
                sumEven += wei[2 * i + 1];
            }
            console.log("奇数位的和是：" + sumOdd);
            console.log("偶数位的和是：" + sumEven);
            if ((sumOdd + sumEven) % 10 == 0) {
                console.log("Recept.");
                return true;
            }
            return false;
        },

        _validateBankCard: function (number) {
            return true;
        },

        _validateSocialSecurityCard: function () {
            return true;
        },

        _validateMobile: function (phoneValue) {
            phoneValue = phoneValue.trim();
            var reg = /^[1][0-9]{10}$/;
            return reg.test(phoneValue);
        },

        _validateUrl: function (url) {
            var strRegex = '^((https|http|ftp|rtsp|mms)?://)'
                + '?(([0-9a-z_!~*\'().&=+$%-]+: )?[0-9a-z_!~*\'().&=+$%-]+@)?' //ftp的user@
                + '(([0-9]{1,3}.){3}[0-9]{1,3}' // IP形式的URL- 199.194.52.184
                + '|' // 允许IP和DOMAIN（域名）
                + '([0-9a-z_!~*\'()-]+.)*' // 域名- www.
                + '([0-9a-z][0-9a-z-]{0,61})?[0-9a-z].' // 二级域名
                + '[a-z]{2,6})' // first level domain- .com or .museum
                + '(:[0-9]{1,4})?' // 端口- :80
                + '((/?)|' // a slash isn't required if there is no file name
                + '(/[0-9a-z_!~*\'().;?:@&=+$,%#-]+)+/?)$';
            var re = new RegExp(strRegex);
            return re.test(url);
        },

        _validatePostCode: function (postcode) {
            return !/^[0-9][0-9]{5}$/.test(postcode);
        },

        _validateEmail: function (email) {
            var reg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
            if (!reg.test(email)) {
                // alert("请输入符合规范的邮箱账号！");
                return false;
            }
            return true;
        },

        /**
         * 验证电话号码
         * @param phoneValue 要验证的电话号码
         * @returns 匹配返回true 不匹配返回false
         */
        _validatePhone: function (phoneValue) {
            phoneValue = phoneValue.trim();
            var reg = /^((0\d{2,3})-)?(\d{7,8})(-(\d{3,}))?$/;
            return reg.test(phoneValue);
        },

        /**
         * 检验18位身份证号码（15位号码可以只检测生日是否正确即可，自行解决）
         *
         * @param idCardValue
         * 18位身份证号
         * @returns 匹配返回true 不匹配返回false
         */
        _validateIDCard: function (cid) {
            var arrExp = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];// 加权因子
            var arrValid = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];// 校验码
            var reg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/;
            if (reg.test(cid)) {
                var sum = 0, idx;
                for (var i = 0; i < cid.length - 1; i++) {
                    // 对前17位数字与权值乘积求和
                    sum += parseInt(cid.substr(i, 1), 10) * arrExp[i];
                }
                // 计算模（固定算法）
                idx = sum % 11;

                // 检验第18为是否与校验码相等
                return arrValid[idx] == cid.substr(17, 1).toUpperCase();
            }
            return false;
        },

        /**
         * 密码采用数字、字母、特殊字符且长度为6-20位
         * @param str
         * @returns {boolean}
         */
        _validatePassword: function (str) {
            if (/^.*?[\d]+.*$/.test(str) && /^.*?[A-Za-z]/.test(str)
                && /^.*?[~/`!@#$%^&*()_+|{}?;:><\-\]\\[\/].*$/.test(str) && /^.{6,20}$/.test(str)) {
                return true;
            }
            return false;
        },

        _execDynamicMethod_: function (funcName, args) {
            if (typeof(eval(funcName)) != "function") {
                throw 'There is not exists a function named:"' + funcName + '"';
            }

            if (!(args instanceof (Array))) {
                throw 'The arguments of function should be a array';
            }

            return this._doCall_(eval(funcName), args);
        },

        _doCall_: function (fn, args) {
            return fn.apply(this, args);
        },

        validate: function () {
            var arrays = [];
            var results = this._checkRequireds();
            for (var index in results) {
                var result = results[index];
                if (!result.status) {
                    arrays.push(result.tip);
                }
            }
            arrays = arrays.notempty();
            if (arrays.length > 0) {
                alert(arrays.join('|'));
                // $("#" + results[0].name).focus();
                return false;
            }

            var result = this._validateSelectComponents();
            if (!result.status) {
                alert(result.tip);
                // $("#" + result.name).focus();
                return false;
            }

            result = this._validateDateComponents();

            if (!result.status) {
                alert(result.tip);
                $("#" + result.name).val();
                // $("#" + result.name).focus();
                return false;
            }
            var formId = $("form")[0].id;
            // if (!this._checkPassword(formId)) {
            //     return false;
            // }

            var res = this._validateDataFormat();
            if (!res.status) {
                var tip = [];
                for (var i = 0; i < res.items.length; i++) {
                    tip.push(res.items[i].tip);
                }
                alert(String.format("%s %s", tip.join('|'), '格式不正确'));

                $("#" + res.items[0].name).val();
                // $("#" + res.items[0].name).focus();
                return false;
            }

            if (Validator.hasCustomValidator) {
                $.each(this.customValidators, function (index, customValidator) {
                    this._execDynamicMethod_(customValidator.option.callback, customValidator.option.args);
                })
            }
            return true;
        }
    };

    Validator.getInstance = function (options) {
        Validator._check(options);

        var validator = new Validator();

        if (!Validator.hasCustomValidator) {
            return validator;
        }

        if (Validator.isOnlyOne) {
            validator.customValidators.push(options);
            return validator;
        }

        $.each(options, function (index, option) {
            validator.customValidators.push(option);
        })

        return validator;
    }
});